import React, { useState, useCallback, useMemo } from 'react';
import { createEditor, Descendant } from 'slate';
import { Editable, Slate, withReact } from 'slate-react';
import { withHistory } from 'slate-history';

import { Element, Leaf, allDecorate, withEditor, hotkeyCall } from '@/core';

import { Menu, HoveringToolbar } from './module/menu';
import { Search } from './module/Search';
import { initialValue, SearchContext } from './share';

export const SlateEditor = () => {
  const [value, setValue] = useState<Descendant[]>(initialValue);
  const [search, setSearch] = useState('');
  const editor = useMemo(() => withEditor(withReact(withHistory(createEditor()))), []);
  const renderElement = useCallback((props) => <Element {...props} />, []);
  const renderLeaf = useCallback((props) => <Leaf {...props} />, []);
  const decorate = useCallback(allDecorate, [search]);
  const onKeyDown = useCallback(hotkeyCall(editor), []);

  return (
    <SearchContext.Provider value={{ search, setSearch }}>
      <Slate editor={editor} value={value} onChange={(value: Descendant[]) => setValue(value)}>
        <Menu />
        <Editable
          renderElement={renderElement}
          renderLeaf={renderLeaf}
          // FIXME: #1 React has detected a change in the order of Hooks called by Editable.
          decorate={decorate}
          // FIXME: #1 React has detected a change in the order of Hooks called by Editable.
          onKeyDown={onKeyDown}
          spellCheck
          autoFocus
          className={'editor'}
        />
        <HoveringToolbar />
        <Search />
      </Slate>
    </SearchContext.Provider>
  );
};
